package com.wgworkshop.pems.service;

import com.wgworkshop.pems.common.BusinessException;
import com.wgworkshop.pems.common.CommonUtils;
import com.wgworkshop.pems.entity.HolidayEntity;
import com.wgworkshop.pems.entity.StudentEntity;
import com.wgworkshop.pems.entity.WorkEntity;
import com.wgworkshop.pems.model.*;
import com.wgworkshop.pems.repository.AttendanceRepository;
import com.wgworkshop.pems.repository.HolidayRepository;
import com.wgworkshop.pems.repository.WorkRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class WorkServiceImpl implements WorkService {
    @Autowired
    private WorkRepository workRepository;
    @Autowired
    private AttendanceRepository attendanceRepository;
    @Autowired
    private HolidayRepository holidayRepository;
    @Autowired
    private StudentService studentService;
    @Autowired
    private OssService ossService;

    @Override
    public WorkModel save(WorkModel workModel) {
        Long studentId = workModel.getStudentId();
        studentService.checkExists(studentId);

        WorkEntity workEntity = new WorkEntity();
        BeanUtils.copyProperties(workModel, workEntity);

        StudentEntity studentEntity = studentService.getRepository().findOne(studentId);
        workEntity.setStudent(studentEntity);

        WorkEntity resultEntity = workRepository.save(workEntity);
        WorkModel resultModel = new WorkModel();
        BeanUtils.copyProperties(resultEntity, resultModel);
        resultModel.setStudentId(resultEntity.getStudent().getId());

        return resultModel;
    }

    @Override
    public void delete(Long id) {
        checkExists(id);

        WorkEntity workEntity = workRepository.findOne(id);
        String object = workEntity.getObject();
        ossService.deleteObject(object);

        workRepository.delete(id);
    }

    @Override
    public WorkModel findOne(Long id) {
        WorkEntity workEntity = workRepository.findOne(id);

        WorkModel workModel = null;
        if (workEntity != null) {
            workModel = new WorkModel();
            BeanUtils.copyProperties(workEntity, workModel);
            workModel.setStudentId(workEntity.getStudent().getId());
        }

        return workModel;
    }

    @Override
    public WorkModel update(Long id, String name) {
        checkExists(id);

        WorkEntity workEntity = workRepository.findOne(id);
        workEntity.setName(name);
        WorkEntity resultEntity = workRepository.save(workEntity);
        WorkModel resultModel = new WorkModel();
        BeanUtils.copyProperties(resultEntity, resultModel);
        resultModel.setStudentId(resultEntity.getStudent().getId());

        return resultModel;
    }

    @Override
    public boolean exists(Long id) {
        return workRepository.exists(id);
    }

    @Override
    public void checkExists(Long id) {
        if (!exists(id)) {
            throw new BusinessException(String.format("指定的作品ID不存在[%s]。", id));
        }
    }

    @Override
    public WorkView getWorkView(int week, int classNum, int shift) {
        if (week < 0 || week > 6) {
            throw new BusinessException("指定的星期应该在0-6之间。");
        }

        CommonUtils.DateBoundary boundary = CommonUtils.calculateBoundaryDate(week, shift, 7, 1);

        List<Long> studentIds = new ArrayList<>();
        Iterable<AttendanceStudentViewRecord> studentViewRecords = attendanceRepository.getAttendanceStudentView(week, classNum);
        for (AttendanceStudentViewRecord studentRecord : studentViewRecords) {
            studentIds.add(studentRecord.getId());
        }

        Iterable<WorkEntity> workEntities = workRepository.findByCourseDateBetweenAndStudentIdIn(boundary.start, boundary.end, studentIds);
        List<WorkModel> workInfo = copyToWorkModel(workEntities);

        Iterable<HolidayEntity> holidayEntities = holidayRepository.findByHolidayBetween(boundary.start, boundary.end);
        List<HolidayModel> holidayInfo = CommonUtils.convertIterableToList(holidayEntities, HolidayModel.class);

        List<WorkViewRecord> viewRecords = new ArrayList<>();
        for (AttendanceStudentViewRecord studentRecord : studentViewRecords) {
            WorkViewRecord viewRecord = new WorkViewRecord();
            viewRecord.setStudentInfo(studentRecord);

            List<WorkModel> workList = new ArrayList<>();
            for (WorkModel work : workInfo) {
                if (studentRecord.getId().compareTo(work.getStudentId()) == 0) {
                    workList.add(work);
                }
            }
            viewRecord.setWorkInfo(workList);

            viewRecords.add(viewRecord);
        }

        WorkView view = new WorkView();
        view.setWorkList(viewRecords);
        view.setHolidayInfo(holidayInfo);

        return view;
    }

    @Override
    public List<WorkPreviewModel> getWorkPreview(int week, int classNum) {
        if (week < 0 || week > 6) {
            throw new BusinessException("指定的星期应该在0-6之间。");
        }

        OssBasicInfo basicInfo = ossService.getBasicInfo();

        List<Long> studentIds = new ArrayList<>();
        Iterable<AttendanceStudentViewRecord> studentViewRecords = attendanceRepository.getAttendanceStudentView(week, classNum);
        for (AttendanceStudentViewRecord studentRecord : studentViewRecords) {
            studentIds.add(studentRecord.getId());
        }

        Sort.Order studentIdOrder = new Sort.Order(Sort.Direction.DESC, "studentId");
        Sort.Order courseDateOrder = new Sort.Order(Sort.Direction.ASC, "courseDate");
        List<Sort.Order> orderList = new ArrayList<>();
        orderList.add(studentIdOrder);
        orderList.add(courseDateOrder);
        Sort sort = new Sort(orderList);

        Iterable<WorkEntity> workEntities = workRepository.findByStudentIdIn(studentIds, sort);

        List<WorkPreviewModel> workPreviewModels = new ArrayList<>();
        WorkPreviewModel workPreviewModel = new WorkPreviewModel();
        boolean foundStudentId;
        for (WorkEntity workEntity : workEntities) {
            foundStudentId = false;
            for (WorkPreviewModel wpm : workPreviewModels) {
                if (wpm.getStudent().getId().longValue() == workEntity.getStudent().getId().longValue()) {
                    foundStudentId = true;
                    break;
                }
            }

            if (!foundStudentId) {
                workPreviewModel = new WorkPreviewModel();

                StudentModel studentModel = new StudentModel();
                BeanUtils.copyProperties(workEntity.getStudent(), studentModel);
                workPreviewModel.setStudent(studentModel);

                workPreviewModel.setWorkList(new ArrayList<>());

                workPreviewModel.setOss(basicInfo);
            }

            WorkModel workModel = new WorkModel();
            BeanUtils.copyProperties(workEntity, workModel);
            workModel.setStudentId(workEntity.getStudent().getId());
            List<WorkModel> workModels = workPreviewModel.getWorkList();
            workModels.add(workModel);

            workPreviewModel.setWorkList(workModels);

            if (!foundStudentId) {
                workPreviewModels.add(workPreviewModel);
            }
        }

        return workPreviewModels;
    }

    private List<WorkModel> copyToWorkModel(Iterable<WorkEntity> workEntities) {
        List<WorkModel> workModels = new ArrayList<>();
        for (WorkEntity workEntity : workEntities) {
            WorkModel workModel = new WorkModel();
            BeanUtils.copyProperties(workEntity, workModel);
            workModel.setStudentId(workEntity.getStudent().getId());
            workModels.add(workModel);
        }
        return workModels;
    }
}
